import os
from apscheduler.schedulers.blocking import BlockingScheduler

from service.data_service import stock_dict
from service import trigger_service, score_service_v1, msg_service
from utils.logger import Logger
from utils import date_util, ave_util, price_util, caiptal_util, msg_util, doc_util, json_util, read_config, \
    k_util_v1
from database.mapper import stock_monitor, monitor_result, user_info

stock_monitor_dict = {}  # 需要监控的股票池
users_dict = {}  # 用户字典
frequency_config = 720  # 定时任务时间 单位秒

users_path = os.path.join(read_config.data_path, 'common', 'users')
result_path = os.path.join(read_config.data_path, 'result', '突破均线')
document_path = os.path.join(read_config.data_path, 'task', 'document', '突破均线')

logger = Logger('突破均线任务1').get_log()


def monitor_task():
    print("定时任务执行时间" + date_util.get_date_time_str())
    task_id = route_task()  # 任务路由
    if task_id == 1:  # macd+ave监控
        monitor_up_down_v1()


def monitor_up_down_v1():
    if check_update(): return  # 检查配置更新
    current_date = date_util.get_date_str()  # 当前时间串
    # 监控冲破均线
    for code in stock_monitor_dict.keys():
        stock_info = json_util.info_to_json(stock_monitor_dict[code])  # 获取当前字典配置
        rt_price = price_util.get_rt_p(code)  # 股票实时价格
        k_line = k_util_v1.day_k_size_rt(code, 10, rt_price)  # 获取最近的10日k线
        ave5 = ave_util.ave_line_price(k_line[0: 5], 5)  # 5日均线价格
        ave10 = ave_util.ave_line_price(k_line, 10)  # 10日均线价格
        stock_info['ave5'] = ave5
        stock_info['ave10'] = ave10
        stock_info['rt_price'] = rt_price
        stock_info['deal_time'] = date_util.get_date_time_str()
        stock_info['rq'] = current_date
        stock_info = score_service_v1.common_exam(stock_info)  # 进行技术形态评分
        stock_info = trigger_service.deal_trigger(stock_info)  # 处理拐点和触发情况
        stock_info = record_into(stock_info)  # 记录交易状况
        stock_monitor_dict[code] = stock_info  # 刷新监控中信息
    send_msg()  # 发送用户消息提示
    update_local_monitor()  # 更新本地监控字典


# 开启监控定时任务
def monitor_up_down():
    # 初始化参数
    init_data()
    # 先执行一次再开启定时任务 方便一次启动监控
    monitor_task()
    # 添加任务,时间间隔30S
    scheduler = BlockingScheduler()
    scheduler.add_job(monitor_task, 'interval', seconds=frequency_config, id='monitor_task')
    scheduler.start()


# 检查有效时间
def route_task():
    task_id = 0
    if not date_util.valid_day(date_util.get_date_str()):
        return task_id
    # 触发任务一（up_down_monitor）
    date_time = date_util.get_date_time()
    hour = date_time.hour
    minute = date_time.minute
    if 9 <= hour < 15 and not (hour == 9 and minute < 35) \
            and not (hour == 11 and minute > 30) and not (hour == 12):
        return 1
    return 0


# 检查信息更新情况
def check_update():
    sm_list = stock_monitor.select_distinct()
    sm_dict = {}
    for sm in sm_list:
        sm_dict[sm['code']] = sm
        if sm['code'] not in stock_monitor_dict.keys():
            stock_monitor_dict[sm['code']] = add_monitor(sm['code'])
    for code in stock_monitor_dict.keys():
        if code not in sm_dict.keys():
            stock_monitor_dict.pop(code)


# 发送消息提示
def send_msg():
    user_list = user_info.selectall()
    for user in user_list:
        prompt_code = user.get('prompt_code')
        if user.get('user_code') == 'system':
            continue
        msg = ''
        user_monitor_list = stock_monitor.select_all(prompt_code)
        for um in user_monitor_list:
            stock_info = stock_monitor_dict[um.get('code')]
            deal_flag = stock_info['deal_flag']
            hold = int(um.get('total_hand'))
            # 1.非持仓 deal_flag = 3 or deal_flag = 4 提示 一次
            # 2.非持仓 deal_flag = 1 or deal_flag = 2 提示 [0, 3, 9, 15, 30, 60, 480]
            # 3.持仓 deal_flag = 3 or deal_flag = 4 提示 [0, 3, 9, 15, 30, 60, 480]
            # 4.持仓 deal_flag = 1 or deal_flag = 2 提示 一次
            # 交易标志 deal_flag = 0  # 1:加仓 2:入仓 3:清仓 4:减仓
            # 提示间隔公式
            pop_list = [0]
            # 非持仓 提示买入
            if hold == 0 and (deal_flag == 1 or deal_flag == 2) \
                    or hold == 1 and (deal_flag == 3 or deal_flag == 4):
                pop_list = [0, 6, 18, 40, 60, 480]
            # 持仓 提示减仓
            elif hold == 1 and deal_flag == 4:
                pop_list = [0, 6, 18, 40, 60, 480]
            # 持仓 提示清仓
            elif hold == 1 and deal_flag == 3:
                pop_list = [0, 6, 18, 40, 60, 960]
            # 提示间隔对比时间戳
            if 'prom_timestamp' not in stock_info.keys():
                continue
            stock_info = refresh_msg(stock_info)  # 更新消息提示
            diff_time = date_util.get_timestamp_now() - stock_info['prom_timestamp']
            cycle_count = int(diff_time / frequency_config)  # 几轮定时任务后
            if cycle_count in pop_list:
                msg_info = stock_info['msg_info']
                for key in msg_info:
                    msg += key + msg_info[key]
                msg += '\n'
        # 处理消息
        msg_util.miao_msg(prompt_code, msg)


# 记录落库
def record_into(stock_info):
    code = stock_info['code']
    name = stock_info['name']
    deal_flag = stock_info['deal_flag']

    # 新增记录方式 + 记录日志
    # 均线 + macd 触发记录
    if deal_flag != 0:
        stock_info = up_the_flow(stock_info)
        stock_info['prom_timestamp'] = date_util.datetime2timestamp(stock_info['deal_time'])
        logger.debug("triggerthedeal:" + str(stock_info))  # 记录日志数据分析使用

    # 数据落库
    if deal_flag != 0:
        stock_info = up_the_flow(stock_info)
        # 标题行
        content_arr = [['编码', '名称', '触发时间', '当前价格', '五日均线', '十日均线', '触发标志', 'MACD', '超大单净流入', '大单净流入', '换手率', '市值']]
        content_arr.append(
            [code, name, stock_info['deal_time'], stock_info['rt_price'], stock_info['ave5'], stock_info['ave10'],
             stock_info['deal_flag'], stock_info['macd'],
             stock_info['sb_io'], stock_info['b_io'],
             stock_info['hsl'], stock_info['sz']])
        # 数据落库
        stock_info['content_arr'] = content_arr
        monitor_data = {'code': code, 'monitor_date': stock_info['rq'],
                        'monitor_name': stock_info['result_file_path'], 'monitor_type': 1,
                        'monitor_result': str(stock_info)}
        monitor_result.insert(monitor_data)
    return stock_info


# 更新资金流
def up_the_flow(stock_info):
    code = stock_info['code']
    if 'flow_up_time' in stock_info.keys():
        last_t = stock_info['flow_up_time']
        now_t = date_util.get_timestamp_now()
        if now_t - last_t > 100:  # 大于100秒更新
            flow = caiptal_util.get_flow(code)
            stock_info['sb_io'] = flow.sb_io
            stock_info['b_io'] = flow.b_io
            stock_info['hsl'] = flow.turnover_rate
            stock_info['sz'] = flow.market_value
            stock_info['flow_up_time'] = now_t
    else:
        flow = caiptal_util.get_flow(code)
        stock_info['sb_io'] = flow.sb_io
        stock_info['b_io'] = flow.b_io
        stock_info['hsl'] = flow.turnover_rate
        stock_info['sz'] = flow.market_value
        stock_info['flow_up_time'] = date_util.get_timestamp_now()
    return stock_info


def init_data():
    monitor_list = doc_util.get_path_doc_info(os.path.join(document_path, 'stock_monitor_dict'))
    for monitor_info in monitor_list:
        monitor_info = json_util.info_to_json(monitor_info)
        stock_monitor_dict[monitor_info['code']] = monitor_info


def update_local_monitor():
    doc_util.gen_a_doc(document_path, 'stock_monitor_dict', stock_monitor_dict)


def add_monitor(code):
    # 初始化
    k_lines = k_util_v1.day_k_size(code, 10)
    ave5 = ave_util.ave_line_price(k_lines[5:10], 5)
    ave10 = ave_util.ave_line_price(k_lines, 10)
    sp_pre = float(json_util.info_to_json(k_lines[9])['sp'])
    flag5 = 1  # 1:监控突破 -1:监控跌破 初始化
    flag10 = 1  # 1:监控突破 -1:监控跌破 初始化
    if sp_pre > ave5: flag5 = -1
    if sp_pre > ave10: flag10 = -1
    deal_flag = 0  # 交易标志 deal_flag = 0  # 0:初始化 1:全仓 2:加半仓 3:清仓 4:减半仓
    monitor_info = {}
    monitor_info['msg'] = ''  # 提示消息
    monitor_info['code'] = code
    monitor_info['ave5'] = ave5
    monitor_info['ave10'] = ave10
    monitor_info['flag5'] = flag5
    monitor_info['flag10'] = flag10
    monitor_info['deal_flag'] = deal_flag
    monitor_info['name'] = stock_dict[code]['name']
    monitor_info['exchange'] = stock_dict[code]['exchange']
    monitor_info['insert_time'] = date_util.get_date_time_str()
    monitor_info['result_file_path'] = '未分类'  # 存储分类路径
    monitor_info['last_deal_time'] = '2000-01-01 00:00:00'  # 最新交易(触犯)日期
    return monitor_info


# 刷新消息
def refresh_msg(stock_info):
    # print('开始刷新消息')
    code = stock_info['code']
    stock_info = up_the_flow(stock_info)
    msg_dict = msg_service.translation_info(stock_info, 1)
    # 最新诊断结果
    res = monitor_result.select_code_type_new_one(code, 3)
    if res:
        msg_dict = dict(msg_dict, **msg_service.translation_info(res['monitor_result'], 3))
    stock_info['msg_info'] = msg_dict
    return stock_info


if __name__ == '__main__':
    # refresh_dict()
    # monitor_up_down()
    # init_monitor_info()
    print(monitor_task())
